﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using Microsoft.Practices.Unity;
using VisualWip.Core;
using VisualWip.PresentationModel;
using Window = System.Windows.Window;

namespace VisualWip
{
    public class WindowManager : IWindowManager
    {
        private readonly Application _application;
        private readonly IUnityContainer _unityContainer;
        private readonly ObservableCollection<WindowViewModel> _windowViewModels;
        private readonly Dictionary<string, Window> _windows;

        public WindowManager(IUnityContainer unityContainer, Application application)
        {
            _unityContainer = unityContainer;
            _windowViewModels = new ObservableCollection<WindowViewModel>();
            _windows = new Dictionary<string, Window>();
            _application = application;
            _application.Windows.CollectionChanged += WindowsCollectionChanged;
        }

        #region IWindowManager Members

        public ObservableCollection<WindowViewModel> WindowViewModels
        {
            get { return _windowViewModels; }
        }

        public void Show(WindowViewModel windowViewModel)
        {
            if (windowViewModel.IsOpen && _windows.ContainsKey(windowViewModel.WindowName))
                _windows[windowViewModel.WindowName].Activate();
            else
                ShowView(windowViewModel);
        }

        public void Close(WindowViewModel windowViewModel)
        {
            if (!windowViewModel.Window.IsMainWindow)
            {
                _windows.Remove(windowViewModel.WindowName);
                windowViewModel.IsOpen = false;
            }
            else
            {
                foreach (var window in _windows.Values)
                {
                    window.Close();
                }
            }
        }

        public void Delete(WindowViewModel windowViewModel)
        {
            if (windowViewModel.IsOpen)
            {
                var window = _windows[windowViewModel.WindowName];
                window.Close();
            }


            _application.DeleteWindow(windowViewModel.Window);
            _windowViewModels.Remove(windowViewModel);
        }

        #endregion

        private void WindowsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    Add(e);
                    break;
                case NotifyCollectionChangedAction.Remove:
                    break;
                case NotifyCollectionChangedAction.Replace:
                    break;
                case NotifyCollectionChangedAction.Move:
                    break;
                case NotifyCollectionChangedAction.Reset:
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        private void Add(NotifyCollectionChangedEventArgs eventArgs)
        {
            foreach (Core.Window window in eventArgs.NewItems.OfType<Core.Window>())
            {
                if (window.IsMainWindow)
                {
                    var mainWindowViewModel = _unityContainer.Resolve<MainWindowViewModel>();
                    var view = new MainWindow { DataContext = mainWindowViewModel };
                    _windowViewModels.Add(mainWindowViewModel);
                    view.Show();
                }
                else
                {
                    var windowViewModel = _unityContainer.Resolve<WindowViewModel>(new DependencyOverride<Core.Window>(window));
                    _windowViewModels.Add(windowViewModel);
                    ShowView(windowViewModel);
                }
            }
        }

        private void ShowView(WindowViewModel windowViewModel)
        {
            var view = new SecondaryWindow { DataContext = windowViewModel };
            windowViewModel.IsOpen = true;
            _windows.Add(windowViewModel.WindowName, view);
            view.Show();
        }
    }
}